package trackListGenerator;

import com.mpatric.mp3agic.ID3v2;
import com.mpatric.mp3agic.InvalidDataException;
import com.mpatric.mp3agic.Mp3File;
import com.mpatric.mp3agic.UnsupportedTagException;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.UUID;

/**
 *
 * @author Aderthad
 */
public class TrackListGenerator {

    private static final String[] allowedCoverExtenstions = new String[]{"jpeg", "jpg", "gif", "png", "tiff"};
    private static final String[] allowedMusicExtenstions = new String[]{"mp3", "m4a", "flac", "wav"};

    private static final ArrayList<Image> imagesToUpload = new ArrayList<>();
    private static final ArrayList<Image> uploadedImages = new ArrayList<>();

    private static final ArrayList<Thread> threads = new ArrayList<>();

    private static final StringBuilder sb = new StringBuilder();

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {

        File root = new File("e:\\Aderthad\\Music\\_k\\Sweet Salt\\");

        if (!root.exists()) {
            System.out.println("File doesn't exist.");
            return;
        }

        System.out.println("Generating tracklist…");

        sb.append("[center]\n" + "[size=\"8\"][b][u]" + root.getName() + " Discography[/u][/b][/size]\n");
        sb.append("\nGenres: "
                + "%ADD%"
                + "\n"
                + "All songs are 320kbps unless stated otherwise.\n"
        //+ "I can usually seed during evenings (GMT).\n\n"
        );

        printChildren(root);

        sb.append("\n[/center]");

        System.out.println("Done generating tracklist.\n");

        String text = sb.toString();

        for (int i = 0; i < 5; i++) {
            Runnable task = new Uploader();
            Thread worker = new Thread(task);
            worker.start();
            threads.add(worker);
        }

        int running = 0;
        do {
            running = 0;
            for (Thread thread : threads) {
                if (thread.isAlive()) {
                    running++;
                }
            }
        } while (running > 0);

        for (Image i : uploadedImages) {
            text = text.replace(i.uuid, "[img]" + i.url + "[/img]");
        }

        System.out.println("\n\n\n" + text);

    }

    private static void printChildren(File file) {

        for (File c : file.listFiles()) {
            if (c.isDirectory()) {
                Boolean b = true;
                for (File ff : c.listFiles()) {
                    if (ff.isDirectory()) {
                        b = false;
                    }
                }
                sb.append("\n");
                if (!b) {
                    sb.append("[size=\"5\"][b][u]" + c.getName() + "[/u][/b][/size]\n");
                } else {
                    File image = getCover(c);
                    if (image != null) {
                        String uuid = "%" + UUID.randomUUID().toString() + "%";
                        sb.append(uuid + "\n");
                        imagesToUpload.add(new Image(image, uuid));
                    }
                    // String bitrate = getBitrate(c);
                    sb.append("[b][u]" + c.getName() + "[/u][/b]\n");
                }
                printChildren(c);
            } else {
                String name = c.getName();
                Boolean folder = false;
                for (File ff : file.listFiles()) {
                    if (ff.isDirectory()) {
                        folder = true;
                        break;
                    }
                }

                if (HasExtention(c, 0)) {
                    if (folder) {
                        sb.append("[SINGLE] ");
                    }
                    sb.append(name.substring(0, name.lastIndexOf(".")) + "\n");
                    if (folder) {
                        sb.append("\n");
                    }
                }

            }
        }

    }

    private static class Uploader implements Runnable {

        private static void uploadImage() {
            Image imageToUpload = null;
            synchronized (imagesToUpload) {
                imageToUpload = imagesToUpload.get(0);
                imagesToUpload.remove(0);
            }

            System.out.println("Uploading cover for " + imageToUpload.getImage().getParentFile().getName() + "…");

            String url = ImgurUploader.upload(imageToUpload.imageFile);
            if (url != null && url.length() > 8 && url.contains("link")) {
                int linkIndexStart = url.indexOf("\"link\":") + 8;
                url = url.substring(linkIndexStart, url.indexOf("\"", linkIndexStart)).replaceAll("\\\\/", "/");

                imageToUpload.setUrl(url);

                synchronized (uploadedImages) {
                    uploadedImages.add(imageToUpload);
                }
                System.out.println("Done uploading cover for " + imageToUpload.getImage().getParentFile().getName() + ".");
            } else {
                System.out.println("Error while uploading cover for " + imageToUpload.getImage().getParentFile().getName() + ".");
            }
        }

        @Override
        public void run() {
            while (!imagesToUpload.isEmpty()) {
                uploadImage();
            }
        }

    }

    private static File getCover(File file) {
        ArrayList<File> images = new ArrayList<>(Arrays.asList(file.listFiles(new FileFilter() {
            @Override
            public boolean accept(File file) {
                return HasExtention(file, 1);
            }
        })));
        for (File image : images) {
            if (image.getName().toLowerCase().startsWith("cover")) {
                return image;
            }
        }
        if (images.size() > 0) {
            return images.get(0);
        } else {
            return null;
        }
    }

    private static String getBitrate(File file) {
        String bitrate = "";
        try {
            DirectoryStream<Path> dirs = Files.newDirectoryStream(file.toPath(), new DirectoryStream.Filter<Path>() {

                @Override
                public boolean accept(Path t) throws IOException {
                    return HasExtention(t.toFile(), 0);
                }
            });

            Iterator it = dirs.iterator();

            if (it.hasNext()) {
                Path firstSong = (Path) it.next();
                String songName = firstSong.getFileName().toString().toLowerCase();
                if (songName.endsWith(".mp3")) {
                    Mp3File mp3file = new Mp3File(firstSong.toString());

                    if (mp3file.hasId3v2Tag()) {
                        ID3v2 tag = mp3file.getId3v2Tag();
                        //bitrate = tag.getEncoder();
                    }
                } else if (songName.endsWith(".flac")) {
                    bitrate = "FLAC";
                }
            }

        } catch (IOException | UnsupportedTagException | InvalidDataException ex) {
            System.out.println(ex.getMessage());
        }

        return bitrate;
    }

    private static boolean HasExtention(File file, int param) {
        String[] filter = null;
        if (param == 0) {
            filter = allowedMusicExtenstions;
        } else if (param == 1) {
            filter = allowedCoverExtenstions;
        } else {
            return false;
        }

        String fileName = file.getName();

        for (String s : filter) {
            if (fileName.toLowerCase().endsWith(s)) {
                return true;
            }
        }
        return false;

    }

    private static class Image {

        File imageFile;
        String uuid;
        String url = "";

        Image(File imageFile, String uuid) {
            this.imageFile = imageFile;
            this.uuid = uuid;
        }

        public File getImage() {
            return imageFile;
        }

        public String getUUID() {
            return uuid;
        }

        public String getUrl() {
            return url;
        }

        public void setUrl(String url) {
            this.url = url;
        }
    }
}
